﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Thor.Common
{
    public class LogUtility
    {
        public class Log
        {
            public string filepath { get; set; }
            public string info { get; set; }
        }
        private List<Log> logs { get; set; }
        private readonly object locker = new object();
        private int waittime { get; set; }

        public string filepath { get; set; }
        private Task TaskWriter;
        private async void WriterLoger()
        {
            List<Log> logs = new List<Log>();
            //StringBuilder logTmp = new StringBuilder();
            Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
            while (true)
            {
                await Task.Delay(waittime);
                try
                {
                    lock (locker)
                    {
                        int Count = this.logs.Count();
                        int count = 10000;
                        if (Count < count)
                        {
                            count = Count;
                        }
                        if (Count > 0)
                        {
                            waittime = 100;
                            logs = this.logs.Take(count).ToList();
                            this.logs.RemoveRange(0, count);
                        }
                        else
                        {
                            waittime = 1000;
                        }
                    }
                    foreach (var log in logs)
                    {
                        if (!dict.ContainsKey(log.filepath))
                        {
                            List<string> list = new List<string>();
                            list.Add(log.info);
                            dict.Add(log.filepath, list);
                        }
                        else
                        {
                            List<string> list = dict[log.filepath];
                            list.Add(log.info);
                            dict[log.filepath] = list;
                        }
                    }
                    foreach (var key in dict.Keys)
                    {
                        try
                        {
                            //logTmp.Clear();
                            //logTmp.Append(dict.info);
                            //logTmp.Append(System.Environment.NewLine);
                            System.IO.File.AppendAllLines(key, dict[key]);
                        }
                        catch (Exception oe)
                        {
                            string err = oe.Message;
                        }
                    }
                }
                catch { }
                dict.Clear();
                logs.Clear();
            }
        }
        public LogUtility()
        {
            logs = new List<Log>();
            waittime = 100;
            TaskWriter = new Task(WriterLoger);
            TaskWriter.Start();
            filepath = null;
        }
        public LogUtility(string filepath)
        {
            logs = new List<Log>();
            waittime = 100;
            TaskWriter = new Task(WriterLoger);
            TaskWriter.Start();
            this.filepath = filepath;
        }
        private List<Log> Dequeue(int count = 1)
        {
            List<Log> value = new List<Log>();
            lock (locker)
            {
                int Count = logs.Count();
                if (Count < count)
                {
                    count = Count;
                }
                if (Count > 0)
                {
                    value = logs.Take(count).ToList();
                    logs.RemoveRange(0, count);
                }
            }
            return value;
        }
        private bool Enqueue(List<Log> logs)
        {
            bool value = false;
            if (logs.Count() > 0)
            {
                lock (locker)
                {
                    try
                    {
                        foreach (var log in logs)
                        {
                            this.logs.Add(log);
                        }
                        value = true;
                    }
                    catch (Exception oe)
                    {
                        string err = oe.Message;
                    }
                }
            }
            return value;
        }
        private bool Enqueue(Log log)
        {
            bool value = false;
            List<Log> logs = new List<Log>();
            logs.Add(log);
            value = Enqueue(logs);
            return value;
        }
        public void SaveLog(string logInfo)
        {
            if (filepath == null)
            {
                throw new Exception("保存路径为空，请手动使用filepath参数，或者修改类filepath属性");
            }
            Task.Run(() =>
            {
                Log log = new Log();
                log.filepath = filepath;
                log.info = logInfo;
                Enqueue(log);
            });
        }
        public void SaveLog(string logInfo, string filepath)
        {
            Task.Run(() =>
            {
                Log log = new Log();
                log.filepath = filepath;
                log.info = logInfo;
                Enqueue(log);
            });
        }
        public void SaveLog(Log log)
        {
            Task.Run(() =>
            {
                Enqueue(log);
            });
        }
        public void SaveLog(List<Log> log)
        {
            Task.Run(() =>
            {
                Enqueue(log);
            });
        }
    }
}
